#region Using directives
using System;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework;
using SharpWind.Resources;
using Microsoft.Xna.Framework.Content;
#endregion

namespace SharpWind.Sound
{
	public class Sound : Resource
	{
		#region Fields

		private Cue xnaSound = null;

		private Vector3 position = Vector3.Zero;

		private Vector3 forward = Vector3.Zero;

		private Vector3 up = Vector3.Zero;

		private Vector3 velocity = Vector3.Zero;

		private SoundManager sound = null;

		private string name = string.Empty;

		#endregion

		#region Constructors

		public Sound( string name )
		{
			if( string.IsNullOrEmpty( name ) )
			{
				throw new ArgumentNullException();
			}

			this.name = name;
		}

		#endregion

		#region Methods

		public void Play()
		{
			if( this.xnaSound.IsStopped )
			{
				this.xnaSound = this.sound.SoundBank.GetCue( this.xnaSound.Name );
			}
			else if( this.xnaSound.IsPaused )
			{
				this.xnaSound.Resume();
				return;
			}

			this.xnaSound.Play();
		}

		public void Play3D()
		{
			this.sound.AudioEmiter.Position = this.position;
			this.sound.AudioEmiter.Forward	= this.forward;
			this.sound.AudioEmiter.Up		= this.up;
			this.sound.AudioEmiter.Velocity = this.velocity;

			this.xnaSound.Apply3D( this.sound.AudioListener, this.sound.AudioEmiter );

			Play();
		}

		public void Pause()
		{
			this.xnaSound.Pause();
		}

		public void Stop()
		{
			this.xnaSound.Stop( AudioStopOptions.Immediate );
		}

		internal override void LoadContent( ContentManager contentManager )
		{
			this.sound		= Engine.Instance.Content.Sounds;
			this.xnaSound	= this.sound.SoundBank.GetCue( name );
		}

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if( this.xnaSound != null )
				{
					if( this.xnaSound.IsPaused || this.xnaSound.IsPlaying )
					{
						this.xnaSound.Stop( AudioStopOptions.Immediate );
					}

					this.xnaSound.Dispose();
					this.xnaSound = null;
				}
			}
		}

		#endregion

		#region Properties

		public Vector3 Position
		{
			get
			{
				return this.position;
			}
			set
			{
				this.position = value;
			}
		}

		public Vector3 Forward
		{
			get
			{
				return this.forward;
			}
			set
			{
				this.forward = value;
			}
		}

		public Vector3 Up
		{
			get
			{
				return this.up;
			}
			set
			{
				this.up = value;
			}
		}

		public Vector3 Velocity
		{
			get
			{
				return this.velocity;
			}
			set
			{
				this.velocity = value;
			}
		}

		#endregion
	}
}
